package com.gitee.wsl.mathematics.matrix.mat2

import com.gitee.wsl.mathematics.matrix.M
import com.gitee.wsl.mathematics.matrix.MatCopyInitializer
import com.gitee.wsl.mathematics.matrix.MatrixD
import com.gitee.wsl.mathematics.matrix.MatrixF
import com.gitee.wsl.mathematics.matrix.MutableMatrix
import com.gitee.wsl.mathematics.matrix.N
import com.gitee.wsl.mathematics.vector.vec2.MutableVector2
import com.gitee.wsl.mathematics.vector.vec2.Vector2

interface MutableMatrix2<T:Number,V: Matrix2<T, V, R>,R:Vector2<T,R>>:Matrix2<T, V,R>,MutableMatrix<T,V,R>{
    override var m00: T get() = proxy[0] ;set(value) { proxy[0] = value }
    override var m01: T get() = proxy[1] ;set(value) { proxy[1] = value }
    override var m10: T get() = proxy[2] ;set(value) { proxy[2] = value }
    override var m11: T get() = proxy[3] ;set(value) { proxy[3] = value }

    override val m: List<MutableVector2<T, R>>

    override val n: List<MutableVector2<T, R>>

    //override fun createVec(indexRage: IntRange) = createVec(indexRage.toList())

    override fun copy(block: MatCopyInitializer<T>): MutableMatrix2<T, V, R>

    override fun copyEmpty() = copy(block ={ _, _ -> zero})

    override fun copyIdentity() = copy(block ={ i, j -> if( i == j) one else zero})

    override fun createVec(indexes: List<Int>): MutableVector2<T, R>


    override operator fun M.get(row: Int) = createVec(rowIndexes(row))

    override operator fun N.get(col: Int) = createVec(colIndexes(col))

    override fun copy(m00: T?, m01: T?,
                      m10: T?, m11: T?) = create(
        m00 ?: this.m00,
        m01 ?: this.m01,
        m10 ?: this.m10,
        m11 ?: this.m11
    )

    fun set(
        m00: T, m01: T,
        m10: T, m11: T
    ){
        this.m00 = m00
        this.m01 = m01
        this.m10 = m10
        this.m11 = m11
    }

/*

    override fun timesAssign(other: V) = set(
        m00 * other.m00 + m01 * other.m10, m00 * other.m01 + m01 * other.m11,
        m10 * other.m00 + m11 * other.m10, m10 * other.m01 + m11 * other.m11
    )
*/

    operator fun M.set(row: Int, m: Vector2<T, *>){
        set(row,0,m[0])
        set(row,1,m[1])
        set(row,2,m[2])
    }

    operator fun N.set(colIndex: Int, m: Vector2<T, *>){
        set(0,colIndex,m[0])
        set(1,colIndex,m[1])
        set(2,colIndex,m[2])
    }

}

interface MutableMatrix2F<V: Matrix2<Float, V, R>,R:Vector2<Float,R>>: MutableMatrix2<Float, V,R>, MatrixF<V,R>

interface MutableMatrix2D<V: Matrix2<Double, V, R>,R:Vector2<Double,R>>: MutableMatrix2<Double, V,R>, MatrixD<V,R>